import asyncio
import io
import os
import struct
import threading
import socket
import time
import websockets
from util import *
from multiprocessing import Process

def delete_pcap_connect(connect_dict, Flag, c):
    c.close()
    connect = connect_dict[Flag]
    connect.remove(c)
    connect_dict[Flag] = connect


def pcap_connect(server_socket, flag, connect_dict):
    while True:
        # 等待客户端连接
        print("Waiting for a connection...")
        connection, client_address = server_socket.accept()
        try:
            print(f"Connection from {client_address}")
            # 接收并处理数据（可选）
            while True:
                data = connection.recv(1024)
                if not data:
                    print("No more data from", client_address)
                    break
                print(f"Received '{data.decode()}' from {client_address}")
                if flag not in connect_dict.keys():
                    connect_dict[flag] = [connection]
                else:
                    temp = connect_dict[flag]
                    temp.append(connection)
                    connect_dict[flag] = temp

        except Exception as e:
            print(str(e))
        finally:
            time.sleep(0.1)


async def send_pcap_data(flag, fileNameList, ws_url, final_time):
    print("pcap send data")
    # 发送第一帧时间戳给到中台
    # 获取文件大小
    with open(fileNameList, "rb") as file:
        byte_data = file.read()
    # # 指定分割的大小，例如 5
    chunk_size = 180 * 1366 + 2
    pack_size = 1366
    # 使用切片操作进行分割
    chunks = [byte_data[i:i + chunk_size] for i in range(0, len(byte_data), chunk_size)]
    for chunk in chunks:
        pack_content = chunk[2:]
        packs = [pack_content[i:i + pack_size] for i in range(0, len(pack_content), pack_size)]
        # 读取头部
        byteHead = pack_content[8:16]
        if len(byteHead) < 8:
            break
        timeStamp = struct.unpack("<Q", byteHead)[0]

        async with websockets.connect(ws_url) as websocket:
            await websocket.send(str(timeStamp))
            response = await websocket.recv()
            final_timestamp = int(response)
            print(f"点云pcap received: {response}")
            final_time[flag] = response
        break


def start_pcap_server(pcap_id, pcap_dict, final_time, connect_dict):
    host = pcap_dict['pcap_host']
    port = pcap_dict['pcap_port']
    fileList = pcap_dict['pcap_files']
    ws_url = pcap_dict['ws_url']
    fps = pcap_dict['pcap_fps']
    Flag = pcap_id

    # 创建一个socket对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 绑定到指定地址和端口
    # server_address = ('127.0.0.1', udp_port)
    # print(f"Starting up on {server_address} ...")
    # server_socket.bind(server_address)

    # 开始监听连接
    # server_socket.listen(1)
    # threading.Thread(target=pcap_connect, args=(server_socket, Flag, connect_dict, )).start()

    # 发送第一帧时间戳给到中台
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    loop.run_until_complete(send_pcap_data(Flag, fileList[0], ws_url, final_time))

    # 等待反馈最大的时间戳
    largst_time = None
    while True:
        if final_time[Flag]:
            largst_time = final_time[Flag]
            # print("pcap_largst_time", largst_time)
            break
        time.sleep(0.01)

    before_time = None
    # before_current_time = None
    for fileNameList in fileList:
        with open(fileNameList, 'rb') as f:
            fileSize = int(f.seek(0, io.SEEK_END))
            # print('fileSize', fileSize)
            f.seek(0, 0)
            nowPosition = 0
            while nowPosition < fileSize:
                # 获取包数
                header = f.read(2)
                Headnum = struct.unpack("<H", header)[0]
                nowPosition += 2
                data = []
                for i in range(Headnum):
                    byteHeadLen = f.read(4)
                    HeadLen = struct.unpack("<I", byteHeadLen)[0]
                    byteMsgLen = f.read(4)
                    MsgLen = struct.unpack("<I", byteMsgLen)[0]
                    byteHead = f.read(HeadLen)
                    timeStamp = struct.unpack("<Q", byteHead)[0]
                    # print("timeStamp", timeStamp)
                    pcap_data = f.read(MsgLen)
                    nowPosition = nowPosition + 16 + MsgLen
                    data.append(pcap_data)

                # 略过前几帧
                if (int(timeStamp) - int(largst_time)) < 0:
                    continue
                # print("pcap time", timeStamp)
                current_time = time.time()
                if fps == 0:
                    if before_time:
                        # time_current = (current_time - before_current_time) * 1000
                        # if time_current > :
                        time.sleep((timeStamp - before_time) / 1000)
                    before_time = timeStamp
                    # before_current_time = time.time()
                if fps > 0:
                    if before_time:
                        if (current_time - before_time) > 1 / fps:
                            print("单帧耗时过大")
                        else:
                            time.sleep(1 / fps - (current_time - before_time))
                    before_time = current_time

                if len(data) != 0:
                    # print("pcap发送数据")
                    for i in range(len(data)):
                        for p in port:
                            server_socket.sendto(data[i], (host, p))

                # if Flag in connect_dict.keys():
                #     connection = connect_dict[Flag]
                #     for c in connection:
                #         try:
                #             c.sendall(pcap_data)
                #         except Exception as e:
                #             delete_pcap_connect(connect_dict, Flag, c)
                #             continue


def pcap_run(config_json):
    final_time = {}
    connect_dict = {}
    fileNameList = {}

    file_path = config_json['file_path']
    local_ip = config_json['local_ip']
    websocket_port = config_json['websocket_port']
    station_num = len(config_json['station'])
    for i in range(station_num):
        # 获取各个基站信息
        station = config_json['station'][i]
        station_path = os.path.join(file_path, station['name'])
        # pcap 目录
        pcap_path = os.path.join(station_path, 'pcap')
        # pcap
        pcap_num = len(station['pcap'])
        for p in range(pcap_num):
            pcap_id = int(station['name'])
            pcap_files = get_folders(pcap_path, pcap_id)
            pcap_host = station['pcap'][p]['pcap_host']
            pcap_port = station['pcap'][p]['pcap_port']
            pcap_fps = station['pcap'][p]['fps']
            if pcap_host == "127.0.0.1":
                while is_port_in_use(pcap_host, pcap_port):
                    time.sleep(0.1)
            ws_url = 'ws://' + str(local_ip) + ':' + str(websocket_port) + '/' + str(station['name']) + '/pcap/' + str(pcap_id)
            fileNameList[pcap_id] = {
                'pcap_files': pcap_files,
                'pcap_host': pcap_host,
                'pcap_port': pcap_port,
                'pcap_fps': pcap_fps,
                'ws_url': ws_url
            }

    for k, v in fileNameList.items():
        # threading.Thread(target=start_pcap_server, args=(k, v, final_time, connect_dict,)).start()
        Process(target=start_pcap_server, args=(k, v, final_time, connect_dict,)).start()


if __name__ == '__main__':
    config_json = {}
    pcap_run(config_json)

